package com.xique.door.biz.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.pagehelper.PageInfo;
import com.xique.common.core.constant.Constants;
import com.xique.common.core.constant.HttpStatus;
import com.xique.common.core.domain.R;
import com.xique.common.core.utils.*;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.common.core.web.page.TableDataInfo;
import com.xique.door.api.dto.BaseUserDTO;
import com.xique.door.api.model.LoginAppUser;
import com.xique.door.api.request.user.RemoteUserListRequest;
import com.xique.door.bean.domain.*;
import com.xique.door.bean.dto.CardDeviceHouseCodeDTO;
import com.xique.door.bean.dto.DoorImportTemplateDTO;
import com.xique.door.bean.request.card.CardAddRequest;
import com.xique.door.bean.request.user.UserAddCardRequest;
import com.xique.door.bean.request.user.UserAddHouseRequest;
import com.xique.door.bean.request.user.UserAddRequest;
import com.xique.door.bean.request.user.UserSelectRequest;
import com.xique.door.bean.search.device.DeviceListSearch;
import com.xique.door.bean.search.user.UserListSearch;
import com.xique.door.bean.transfer.UserHouseTransfer;
import com.xique.door.bean.validation.UserValidation;
import com.xique.door.bean.vo.user.*;
import com.xique.door.biz.service.IBuildHouseUserBizService;
import com.xique.door.biz.service.IUserBizService;
import com.xique.door.biz.service.IUserCardBizService;
import com.xique.door.command.ICardCommandBizService;
import com.xique.door.command.IDeviceUserCommandService;
import com.xique.door.device.freeview.constant.CommandStatus;
import com.xique.door.service.*;
import com.xique.park.api.RemoteParkCarService;
import com.xique.park.api.request.RemoteParkCarRequest;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: caogq @Date: 2022/1/21 16:28 @Description:
 */
@Service
@Slf4j
public class UserBizServiceImpl implements IUserBizService {

    @Autowired
    private IUserService userService;

    @Autowired
    private IBaseUserService baseUserService;

    @Autowired
    private IBuildHouseUserBizService houseUserBizService;

    @Autowired
    private IUserCardBizService userCardBizService;

    @Autowired
    private IDCardService cardService;

    @Autowired
    private IBuildHouseUserService houseUserService;

    @Autowired
    private IBuildHouseService buildHouseService;

    @Autowired
    private UserValidation userValidation;

    @Autowired
    private IUserDomainService userDomainService;

    @Autowired
    private UserHouseTransfer userHouseTransfer;

    @Autowired
    private IBuildBuildingService buildBuildingService;

    @Autowired
    private IBuildAreaService buildAreaService;

    @Autowired
    private IDCardHouseService cardHouseService;

    @Autowired
    private IUserDeviceService userDeviceService;

    @Autowired
    private IAreaService areaService;

    @Autowired
    private IParkInfoService parkInfoService;

    @Autowired
    private IDeviceUserCommandService deviceUserCommandService;

    @Autowired
    private IAccessDeviceService accessDeviceService;

    @Autowired
    private IUserCompanyService userCompanyService;

    @Autowired
    private RemoteParkCarService remoteParkCarService;

    @Autowired
    private IDCardDeviceService cardDeviceService;

    @Autowired
    private ICardCommandBizService cardCommandBizService;

    @Override
    //    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addUser(UserAddRequest request) {
        // 1、基础用户新增
        BaseUser baseUser = OrikaUtil.convert(request, BaseUser.class);
        if (!StringUtils.isEmpty(request.getPhone())) {
            // 如果用户有手机号，查询该手机号是否存在baseUser
            List<BaseUser> baseUsers =
                    baseUserService.selectBaseUserList(new BaseUser(request.getPhone()));
            if (baseUsers.isEmpty()) {
                baseUser.setCellphone(request.getPhone());
                baseUser.setRemark(" 新增保存门禁用户信息添加");
                baseUserService.insertBaseUser(baseUser);
            } else {
                baseUser = baseUsers.get(0);
            }
        } else {
            // 如果用户没有手机号
            baseUser.setRemark("新增保存门禁用户信息添加，用户没有手机号");
            baseUserService.insertBaseUser(baseUser);
        }

        // 2、项目用户新增
        User user = OrikaUtil.convert(request, User.class);
        user.setBaseUserId(baseUser.getId());
        user.setUserType(0);
        userService.insertUser(user);

        // 2.1. 用户绑定企业
        if (StringUtils.isNotNull(request.getCompanyId())) {
            UserCompany userCompany = new UserCompany();
            userCompany.setCompanyId(request.getCompanyId());
            userCompany.setUserId(user.getId());

            userCompanyService.insertUserCompany(userCompany);
        }

        // 3、绑定用户和房屋，下发用户到房屋绑定的设备
        List<UserAddHouseRequest> houses = request.getHouses();
        if (CollectionUtils.isEmpty(houses)) {
            return AjaxResult.success();
        }
        UserAddHouseRequest userAddHouseRequest = houses.get(0);
        if (StringUtils.isNull(userAddHouseRequest.getHouseId())) {
            return AjaxResult.success();
        }
        AjaxResult result = houseUserBizService.userAddHouses(user, userAddHouseRequest);
        if (AjaxResult.isError(result)) {
            return result;
        }

        // 4、绑定卡片和房屋，下发卡片到房屋绑定的设备
        for (UserAddCardRequest userAddCardRequest : userAddHouseRequest.getCards()) {
            if (StringUtils.isEmpty(userAddCardRequest.getCardSn())) {
                continue;
            }
            CardAddRequest cardAddRequest = OrikaUtil.convert(userAddCardRequest, CardAddRequest.class);
            cardAddRequest.setUserId(user.getId());
            cardAddRequest.setParkId(SecurityUtils.getParkId());
            cardAddRequest.setHouseIds(Collections.singletonList(userAddHouseRequest.getHouseId()));
            // 一卡多房屋，处理卡片房屋
            AjaxResult addCardResult = addCard(cardAddRequest);
            if (AjaxResult.isError(addCardResult)) {
                return addCardResult;
            }
        }
        downCards(user.getId());

        return AjaxResult.success();
    }

    public void downCards(Long userId) {
        DCard dCard = new DCard();
        dCard.setUserId(userId);
        List<DCard> cards = cardService.selectCardList(dCard);
        System.out.println(cards.size());
        UserDevice userDevice = new UserDevice();
        userDevice.setUserId(userId);
        List<UserDevice> userDeviceList = userDeviceService.selectUserDeviceList(userDevice);
        System.out.println(userDeviceList.size());
        List<AccessDevice> accessDevices = new ArrayList<>();
        for (UserDevice userDevice1 : userDeviceList) {

            AccessDevice accessDevice = accessDeviceService.selectAccessDeviceById(userDevice1.getDeviceId());
            accessDevices.add(accessDevice);
        }
        cardCommandBizService.downCards(accessDevices, cards);
    }

    public AjaxResult addCardValidation(CardAddRequest request) {
        if (StringUtils.isEmpty(request.getCardSn()) || request.getUserId() == null || StringUtils.isEmpty(request.getCardType())) {
            return AjaxResult.error("必填项不能为空");
        }
        DCard select = new DCard();
        select.setParkId(request.getParkId());
        select.setCardSn(request.getCardSn());
        List<DCard> dCardList = cardService.selectCardList(select);
        //卡号没有被添加过
        if (!CollectionUtils.isEmpty(dCardList)) {
            User user = userService.selectUserById(dCardList.get(0).getUserId());
            if (user != null) {
                return AjaxResult.error("发卡失败！卡号【" + request.getCardSn() + "】已经被住户【" + user.getUserName() + "】绑定。");
            }
        }
        return AjaxResult.success();
    }

    public AjaxResult addCard(CardAddRequest request) {
        AjaxResult result = addCardValidation(request);
        if (AjaxResult.isError(result)) {
            return result;
        }
        DCard card = OrikaUtil.convert(request, DCard.class);

        card.setCreateUser(SecurityUtils.getUserId());
        card.setUpdateUser(SecurityUtils.getUserId());

        if (!CollectionUtils.isEmpty(request.getHouseIds())) {
            card.setHouseIds(org.apache.commons.lang.StringUtils.join(request.getHouseIds(), ","));
        }

        DCard search = new DCard();
        search.setParkId(SecurityUtils.getParkId());
        search.setCardSn(card.getCardSn());
        List<DCard> dCards = cardService.selectCardList(search);
        if (!dCards.isEmpty()) {
            //card =dCards.get(0);
            card.setId(dCards.get(0).getId());
            card.setStatus("1");
            cardService.updateDCard(card);
            card = cardService.selectDCardById(card.getId());
        } else {
            // 1、db：新增卡片
            card.setCustomId(System.currentTimeMillis() + MathUtil.getRandom(19));
            int count = cardService.insertDCard(card);
            if (count < 0) {
                return AjaxResult.error("新增卡片失败");
            }
        }
        List<Long> houseIds = request.getHouseIds();
        if (CollectionUtils.isEmpty(houseIds)) {
            return AjaxResult.success();
        }

        // 3、db：中间表数据新增
        for (Long houseId : request.getHouseIds()) {
            // 新增房屋卡片表
            DCardHouse dCardHouse = new DCardHouse();
            dCardHouse.setHouseId(houseId);
            dCardHouse.setParkId(card.getParkId());
            dCardHouse.setCardId(card.getId());
            dCardHouse.setUserId(request.getUserId());
            cardHouseService.insertDCardHouse(dCardHouse);
        }
        List<CardDeviceHouseCodeDTO> dtos = houseUserService.selectHouseCodesByCard(card);
        if (dtos.isEmpty()) {
            return AjaxResult.success();
        }
        List<Long> deviceIds =
                dtos.stream()
                        .distinct()
                        .map(CardDeviceHouseCodeDTO::getDeviceId)
                        .collect(Collectors.toList());
        List<AccessDevice> accessDevices = accessDeviceService.selectAccessDeviceByIds(deviceIds);
        List<CardDevice> cardDevices = new ArrayList<>();
        for (AccessDevice accessDevice : accessDevices) {
            CardDevice cardDevice = new CardDevice();
            cardDevice.setDeviceId(accessDevice.getId());
            cardDevice.setParkId(request.getParkId());
            cardDevice.setCustomId(card.getCustomId());
            cardDevice.setCardSn(card.getCardSn());
            cardDevice.setModel(accessDevice.getModel());
            cardDevice.setStatus(CommandStatus.SEND);
            cardDevice.setDevSn(accessDevice.getDevSn());
            cardDevice.setCardId(card.getId());
            cardDevice.setCreateBy(String.valueOf(SecurityUtils.getUserId()));
            cardDevice.setUpdateBy(cardDevice.getCreateBy());
            cardDeviceService.insertDCardDevice(cardDevice);
            cardDevices.add(cardDevice);
        }
//
//        AjaxResult downResult = cardCommandBizService.downCard(card, cardDevices, dtos);
//        return downResult;

        return AjaxResult.success();
    }


    @Override
    public AjaxResult detail(Long id) {
        // UserAddRequest
        User user = userService.selectUserById(id);
        UserDetailVo userDetailVo = OrikaUtil.convert(user, UserDetailVo.class);

        UserCompany userCompany = userCompanyService.selectUserCompanyById(user.getId());
        if (StringUtils.isNotNull(userCompany)) {
            userDetailVo.setCompanyId(userCompany.getCompanyId());
        }

        BuildHouseUser buildHouseUser = new BuildHouseUser();
        buildHouseUser.setUserId(id);
        List<BuildHouseUser> buildHouseUsers =
                houseUserService.selectBuildHouseUserList(buildHouseUser);
        List<UserHouseVo> userHouseVos = new ArrayList<>();
        for (BuildHouseUser houseUser : buildHouseUsers) {
            UserHouseVo userHouseVo = new UserHouseVo();
            BuildHouse house = buildHouseService.selectBuildHouseById(houseUser.getHouseId());
            BuildBuilding buildBuilding =
                    buildBuildingService.selectBuildBuildingById(house.getBuildingId());
            BuildArea buildArea = buildAreaService.selectBuildAreaById(buildBuilding.getAreaId());
            userHouseVo.setIdentityType(houseUser.getIdentityType());
            userHouseVo.setHouseCode(house.getHouseCode());
            userHouseVo.setBuildingName(house.getBuildingName());
            userHouseVo.setAreaName(buildArea.getAreaName());
            userHouseVo.setRelation(houseUser.getRelation());
            // 房卡封装
            DCardHouse dCardHouse = new DCardHouse();
            dCardHouse.setHouseId(houseUser.getHouseId());
            dCardHouse.setUserId(id);
            List<DCardHouse> cardHouses = cardHouseService.selectDCardHouseList(dCardHouse);
            if (!cardHouses.isEmpty()) {
                List<Long> cardIds =
                        cardHouses.stream().map(DCardHouse::getCardId).collect(Collectors.toList());
                List<DCard> dCards = cardService.selectDCardByIds(cardIds, null);
                userHouseVo.setUserCardVos(OrikaUtil.converts(dCards, UserCardVo.class));
            }
            userHouseVos.add(userHouseVo);
        }
        UserDevice userDevice = new UserDevice();
        userDevice.setUserId(user.getId());
        List<UserDevice> userDevices = userDeviceService.selectUserDeviceList(userDevice);
        userDetailVo.setUserHouseVos(userHouseVos);

        userDetailVo.setUserDevices(toUserDevice(userDevices));
        return AjaxResult.success(userDetailVo);
    }

    public List<UserDevice> toUserDevice(List<UserDevice> userDevices) {
        for (UserDevice dve : userDevices) {
            AccessDevice accessDevice = accessDeviceService.selectAccessDeviceById(dve.getDeviceId());
            if (StringUtils.isNotNull(accessDevice)) {
                dve.setDevName(accessDevice.getName());
            }
        }
        return userDevices;
    }

    /**
     * @param request
     * @description: 用户列表
     * @author caogq
     * @date: 2022/1/25 15:11 @Param
     */
    @Override
    public List<UserListVo> selectConditionUserList(UserSelectRequest request) {
        List<UserListVo> userListVos = userService.selectConditionUserList(request);
        if (!userListVos.isEmpty()) {
            // 通过userid，查出用户的房屋信息
            List<UserHouseVo> houseBuildingAreaDaos =
                    userHouseTransfer.transferUserListVo(
                            userListVos.stream().map(UserListVo::getId).collect(Collectors.toList()));
            userListVos.forEach(
                    e -> {
                        List<UserHouseVo> userHouseVos =
                                houseBuildingAreaDaos.stream()
                                        .filter(dao -> dao.getUserId().equals(e.getId()))
                                        .collect(Collectors.toList());
                        e.setUserHouseVos(userHouseVos);
                    });
        }
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setRows(userListVos);
        rspData.setMsg("查询成功");
        rspData.setTotal(new PageInfo(userListVos).getTotal());
        return userListVos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult remove(String ids) {
        List<String> userIds = Arrays.asList(ids.split(","));
        ParkInfo parkInfo = parkInfoService.selectParkInfoById(SecurityUtils.getParkId());
        StringBuilder msg = new StringBuilder();
        for (String id : userIds) {
            Long userId = Long.valueOf(id);
            User user = new User();
            user.setId(userId);
            AjaxResult checkResult = userValidation.deleteUser(user);
            if (AjaxResult.isError(checkResult)) {
                return checkResult;
            }


            if ("Y".equals(parkInfo.getIsPark())) {
                //车场启用停车，需要判断用户是否录入车辆，有则不让删除
                RemoteParkCarRequest remoteParkCarRequest = new RemoteParkCarRequest();
                remoteParkCarRequest.setParkUserId(Long.valueOf(id));
                AjaxResult result = remoteParkCarService.simpleParkCarList(remoteParkCarRequest);
                List<Object> list = (List<Object>) result.get("data");
                if (list != null && list.size() > 0) {
                    User users = userService.selectUserById(Long.valueOf(userId));
                    if (users != null) {
                        msg.append("用户[" + users.getUserName() + "]已绑定车辆，无法删除!").append(Constants.BR);
                        continue;
                    }
                }
            }

            AjaxResult deleteResult = userDomainService.deleteUser(userId);
            if (AjaxResult.isError(deleteResult)) {
                return deleteResult;
            }

        }

        return AjaxResult.success(StringUtils.isEmpty(msg.toString()) ? "用户删除成功，设备同步成功" : msg.toString());
    }

    /**
     * @param
     * @description: 修改用户
     * @author caogq
     * @date: 2022/3/28 19:15 @Param
     */
    @Override
    public AjaxResult updateUser(User request) {
        User user = userService.selectUserById(request.getId());
        String newFaceUrl = request.getFaceUrl();
        String orignFaceUrl = user.getFaceUrl();
        request.setUserType(0);
        userService.updateUser(request);
        User newUser = userService.selectUserById(request.getId());


        // 修改人员信息同步修改base_user和t_user
        User user1 = userService.selectUserById(request.getId());
        getbaseUser(user1);

        if (StringUtils.isNotEmpty(newFaceUrl) && !newFaceUrl.equals(orignFaceUrl)) {
            // 人脸数据已经修改需要重新下发用户
            this.downUser(newUser);
        }

        if (StringUtils.isNotNull(request.getCompanyId())) {
            UserCompany userCompany = userCompanyService.selectUserCompanyById(user.getId());
            if (StringUtils.isNull(userCompany)) {
                UserCompany insert = new UserCompany();
                insert.setUserId(user.getId());
                insert.setCompanyId(request.getCompanyId());

                userCompanyService.insertUserCompany(insert);
            }
            if (StringUtils.isNotNull(userCompany)
                    && !userCompany.getCompanyId().equals(request.getCompanyId())) {
                UserCompany update = new UserCompany();
                update.setUserId(user.getId());
                update.setCompanyId(request.getCompanyId());

                userCompanyService.updateUserCompany(update);
            }
        }

        return AjaxResult.success();
    }

    // 修改人员信息同步修改base_user和t_user
    public void getbaseUser(User user1) {
        BaseUser baseUser = new BaseUser();
        if (user1.getBaseUserId() != null) {
            Long baseUserId = null;
            if (StringUtils.isNotEmpty(user1.getUserName())) {
                baseUser.setUserName(user1.getUserName());
            }
            baseUser.setGender(user1.getGender());
            if (StringUtils.isNotEmpty(user1.getPhone())) {
                baseUser.setCellphone(user1.getPhone());
            }
            baseUser.setBirthday(user1.getBirthday());
            if (StringUtils.isNotEmpty(user1.getFaceUrl())) {
                baseUser.setFaceUrl(user1.getFaceUrl());
            }
            if (StringUtils.isNotEmpty(user1.getFaceKey())) {
                baseUser.setFaceKey(user1.getFaceKey());
            }
            if (user1.getPhone() != null && !"".equals(user1.getPhone())) {
                BaseUserV1 baseUser1 = baseUserService.selectBaseUserV1sCellphone(user1.getPhone());

                if (StringUtils.isNotNull(baseUser1)) {
                    baseUser.setId(baseUser1.getId());
                    baseUserId = user1.getBaseUserId();
                } else {
                    baseUser.setId(user1.getBaseUserId());
                }
            }
            baseUserService.updateBaseUser(baseUser);
            User users = new User();
            if (baseUserId != null) {
                users.setBaseUserId(baseUserId);
            } else {
                users.setBaseUserId(user1.getBaseUserId());
            }
            users.setDelFlag(0);
            List<User> userList = userService.selectUserList(users);
            for (User user2 : userList) {
                if (StringUtils.isNotEmpty(baseUser.getUserName())) {
                    user2.setUserName(baseUser.getUserName());
                }
                if (baseUserId != null) {
                    user2.setBaseUserId(baseUser.getId());
                }
                user2.setGender(baseUser.getGender());

                if (StringUtils.isNotEmpty(baseUser.getCellphone())) {
                    user2.setPhone(baseUser.getCellphone());
                }
                user2.setBirthday(baseUser.getBirthday());
                if (StringUtils.isNotEmpty(baseUser.getFaceUrl())) {
                    user2.setFaceUrl(baseUser.getFaceUrl());
                }
                if (StringUtils.isNotEmpty(baseUser.getFaceKey())) {
                    user2.setFaceKey(baseUser.getFaceKey());
                }
                user2.setUserType(0);
                userService.updateUser(user2);
            }
        }
    }

    /**
     * @param user
     * @description: 修改用户
     * @author caogq
     * @date: 2022/3/28 19:15 @Param
     */
    @Override
    public AjaxResult downUser(User user) {
        // 1、查出用户所绑定的设备
        UserDevice search = new UserDevice();
        search.setUserId(user.getId());
        List<UserDevice> userDevices = userDeviceService.selectUserDeviceList(search);

        if (userDevices.isEmpty()) {
            return AjaxResult.success();
        }
        List<Long> deviceIds =
                userDevices.stream().map(UserDevice::getDeviceId).collect(Collectors.toList());
        List<AccessDevice> accessDevices = accessDeviceService.selectAccessDeviceByIds(deviceIds);
        // 2、下发用户到这些设备
        for (UserDevice userDevice : userDevices) {
            AccessDevice accessDevice =
                    accessDevices.stream()
                            .filter(e -> e.getId().equals(userDevice.getDeviceId()))
                            .findAny()
                            .orElse(null);
            if (accessDevice != null
                    && (StringUtils.isEmpty(accessDevice.getOnlineStatus())
                    || "offline".equals(accessDevice.getOnlineStatus()))) {
                userDevice.setStatus(CommandStatus.PENDING);
            } else {
                if (StringUtils.isNotEmpty(user.getFaceUrl())) {
                    userDevice.setStatus(CommandStatus.SEND);
                } else {
                    userDevice.setStatus(CommandStatus.NOFACE);
                }
            }
            userDevice.setUpdateTime(new Date());
        }
        // 3、下发前修改下发状态
        int i = userDeviceService.batchUpdateUserDevice(userDevices);
        if (StringUtils.isNotEmpty(user.getFaceUrl())) {
            AjaxResult result =
                    deviceUserCommandService.downDevicesUsers(accessDevices, Collections.singletonList(user));
            if (AjaxResult.isError(result)) {
                return result;
            }
        }
        return i > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    /**
     * ========================================================= adminApi/v1
     * =========================================================== *
     */
    @Override
    public List<DoorImportTemplateDTO> getDownloadImportTemplateData() {

        List<DoorImportTemplateDTO> list = new ArrayList<>();

        DoorImportTemplateDTO dto = new DoorImportTemplateDTO();
        dto.setId(1L);
        dto.setAreaName("东区");
        dto.setBuildingName("1幢1单元");
        dto.setHouseName("0101");
        dto.setUserName("住户名称");
        dto.setGender("0");
        dto.setPhone("18888888888");
        dto.setProvince("浙江省");
        dto.setCity("绍兴市");
        dto.setDistrict("越城区");
        dto.setAddress("金滩大厦10楼");

        list.add(dto);

        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult importData(List<DoorImportTemplateDTO> list, boolean updateSupport) {

        Long parkId = SecurityUtils.getParkId();

        if (CollectionUtils.isEmpty(list)) {
            return AjaxResult.error("导入文件中数据为空");
        }

        dealAreaData(parkId, list);

        dealBuildingData(parkId, list);

        dealHouseData(parkId, list);

        dealUserData(parkId, list);

        // TODO 房屋用户
        List<BuildHouseUserV1> insertHouseUserList = new ArrayList<>();
        for (DoorImportTemplateDTO dto : list) {
            BuildHouseUserV1 houseUser = new BuildHouseUserV1();
            houseUser.setUserId(dto.getUserId());
            houseUser.setUserName(dto.getUserName());
            houseUser.setHouseId(dto.getHouseId());
            houseUser.setHouseName(dto.getHouseName() + "室");
            houseUser.setIdentityType("0");
            houseUser.setBuildingId(dto.getBuildingId());
            houseUser.setBuildingName(dto.getBuildingName());
            insertHouseUserList.add(houseUser);
        }

        houseUserService.saveBatch(insertHouseUserList);

        ParkInfo update = new ParkInfo();
        update.setId(parkId);
        update.setInitImport(1);
        parkInfoService.updateParkInfoById(update);

        return AjaxResult.success("导入完成");
    }

    private void dealUserData(Long parkId, List<DoorImportTemplateDTO> list) {

        // TODO 用户
        List<String> provinceNames =
                list.stream()
                        .map(item -> item.getProvince().trim())
                        .distinct()
                        .collect(Collectors.toList());
        List<String> cityNames =
                list.stream().map(item -> item.getCity().trim()).distinct().collect(Collectors.toList());
        List<String> districtNames =
                list.stream()
                        .map(item -> item.getDistrict().trim())
                        .distinct()
                        .collect(Collectors.toList());

        List<Area> provinces = areaService.selectAreaByNames(provinceNames);
        Map<String, Long> provinceMap = new HashMap<>(provinces.size());
        if (!CollectionUtils.isEmpty(provinces)) {
            provinceMap =
                    provinces.stream().collect(Collectors.toMap(Area::getAreaName, Area::getAreaId));
        }

        List<Area> citys = areaService.selectAreaByNames(cityNames);
        Map<String, Long> cityMap = new HashMap<>(citys.size());
        if (!CollectionUtils.isEmpty(citys)) {
            cityMap = citys.stream().collect(Collectors.toMap(Area::getAreaName, Area::getAreaId));
        }

        List<Area> districts = areaService.selectAreaByNames(districtNames);
        Map<String, Long> districtMap = new HashMap<>(districts.size());
        if (!CollectionUtils.isEmpty(districts)) {
            districtMap =
                    districts.stream().collect(Collectors.toMap(Area::getAreaName, Area::getAreaId));
        }

        List<UserV1> insertUserList = new ArrayList<>();
        for (DoorImportTemplateDTO dto : list) {
            if (StringUtils.isNotEmpty(dto.getUserName())) {
                UserV1 user = new UserV1();
                user.setParkId(parkId);
                user.setUserName(dto.getUserName().trim());
                user.setGender(dto.getGender());
                user.setPhone(dto.getPhone().trim());
                // 32位id生成逻辑 = 13位时间戳+19位随机数
                user.setCustomId(System.currentTimeMillis() + MathUtil.getRandom(19));
                user.setType("0");
                if (StringUtils.isNotNull(provinceMap.get(dto.getProvince()))) {
                    user.setProvinceId(provinceMap.get(dto.getProvince()));
                }
                if (StringUtils.isNotNull(cityMap.get(dto.getCity()))) {
                    user.setCityId(cityMap.get(dto.getCity()));
                }
                if (StringUtils.isNotNull(districtMap.get(dto.getDistrict()))) {
                    user.setDistrictId(districtMap.get(dto.getDistrict()));
                }
                user.setAddress(dto.getAddress());
                user.setExportIds(Collections.singletonList(dto.getId()));
                user.setBuildingId(dto.getBuildingId().toString());
                user.setBuildingName(dto.getBuildingName());
                user.setHouseId(dto.getHouseId());
                user.setHouseName(dto.getHouseName() + "室");
                user.setCreateTime(DateUtils.getNowDate());
                user.setCreateUser(SecurityUtils.getUserId());
                insertUserList.add(user);
            }
        }

        List<UserV1> repeatUserList = new ArrayList<>();
        Map<String, UserV1> repeatMap = new HashMap<>(repeatUserList.size());
        for (UserV1 user : insertUserList) {
            String key = user.getUserName() + user.getPhone();
            if (repeatMap.containsKey(key)) {
                UserV1 u = repeatMap.get(key);
                List<Long> exportIds = u.getExportIds();
                exportIds.addAll(user.getExportIds());
                u.setExportIds(exportIds);
                repeatUserList.add(user);
            } else {
                repeatMap.put(key, user);
            }
        }

        if (!CollectionUtils.isEmpty(repeatUserList)) {
            insertUserList.removeAll(repeatUserList);
        }

        List<BaseUserV1> baseUserList =
                OrikaUtil.converts(
                        insertUserList.stream()
                                .filter(item -> StringUtils.isNotEmpty(item.getPhone()))
                                .collect(Collectors.toList()),
                        BaseUserV1.class,
                        Collections.singletonMap("phone", "cellphone"));

        baseUserService.saveBatch(baseUserList);
        Map<String, Long> baseUserMap =
                baseUserList.stream()
                        .collect(Collectors.toMap(BaseUserV1::getCellphone, BaseUserV1::getId));
        insertUserList.forEach(
                item -> {
                    if (StringUtils.isNotNull(baseUserMap.get(item.getPhone()))) {
                        item.setBaseUserId(baseUserMap.get(item.getPhone()));
                    }
                });

        userService.saveBatch(insertUserList);
        Map<Long, UserV1> userMap = new HashMap<>();
        insertUserList.forEach(
                item -> {
                    for (Long exportId : item.getExportIds()) {
                        userMap.put(exportId, item);
                    }
                });

        for (DoorImportTemplateDTO dto : list) {
            if (StringUtils.isNotNull(userMap.get(dto.getId()))) {
                dto.setUserId(userMap.get(dto.getId()).getId());
            }
        }
    }

    private void dealHouseData(Long parkId, List<DoorImportTemplateDTO> list) {

        // TODO 房屋
        List<BuildHouseV1> insertHouseList = new ArrayList<>();
        for (DoorImportTemplateDTO dto : list) {
            BuildHouseV1 house = new BuildHouseV1();
            house.setParkId(parkId);
            house.setBuildingId(dto.getBuildingId());
            house.setBuildingName(dto.getBuildingName());
            String houseCode = dto.getHouseName();
            house.setHouseCode(houseCode.length() == 4 ? houseCode : "0" + houseCode);
            house.setCode(dto.getBuildingCode() + house.getHouseCode());
            house.setHouseName(dto.getHouseName() + "室");
            house.setExportId(dto.getId());
            house.setCreateTime(DateUtils.getNowDate());
            house.setCreateBy(SecurityUtils.getUserId());
            insertHouseList.add(house);
        }

        buildHouseService.saveBatch(insertHouseList);
        Map<Long, BuildHouseV1> houseMap =
                insertHouseList.stream().collect(Collectors.toMap(BuildHouseV1::getExportId, o -> o));
        for (DoorImportTemplateDTO dto : list) {
            if (StringUtils.isNotNull(houseMap.get(dto.getId()))) {
                dto.setHouseId(houseMap.get(dto.getId()).getId());
            }
        }
    }

    private void dealBuildingData(Long parkId, List<DoorImportTemplateDTO> list) {
        // TODO 楼栋
        List<String> buildingNames =
                list.stream()
                        .map(item -> item.getBuildingName().trim())
                        .distinct()
                        .collect(Collectors.toList());
        List<BuildBuildingV1> insertBuildingList = new ArrayList<>();
        for (String name : buildingNames) {
            DoorImportTemplateDTO dto =
                    list.stream().filter(item -> name.equals(item.getBuildingName())).findAny().orElse(null);
            BuildBuildingV1 building = new BuildBuildingV1();
            building.setParkId(parkId);
            building.setAreaId(dto.getAreaId());
            int index1 = name.indexOf("幢");
            int index2 = name.indexOf("单元");
            String buildingCode = name.substring(0, index1);
            building.setBuildingCode(buildingCode.length() == 1 ? "0" + buildingCode : buildingCode);
            String unitCode = name.substring(index1 + 1, index2);
            building.setUnitCode(unitCode.length() == 1 ? "0" + unitCode : unitCode);
            building.setCode(dto.getAreaCode() + building.getBuildingCode() + building.getUnitCode());
            building.setBuildingName(name);
            building.setCreateTime(DateUtils.getNowDate());
            building.setCreateBy(SecurityUtils.getUserId());
            insertBuildingList.add(building);
        }

        buildBuildingService.saveBatch(insertBuildingList);
        Map<String, BuildBuildingV1> buildingMap =
                insertBuildingList.stream()
                        .collect(Collectors.toMap(BuildBuildingV1::getBuildingName, o -> o));
        for (DoorImportTemplateDTO dto : list) {
            if (StringUtils.isNotNull(buildingMap.get(dto.getBuildingName()))) {
                dto.setBuildingId(buildingMap.get(dto.getBuildingName()).getId());
                dto.setBuildingCode(buildingMap.get(dto.getBuildingName()).getCode());
            }
        }
    }

    private void dealAreaData(Long parkId, List<DoorImportTemplateDTO> list) {
        // TODO 区域
        List<String> areaNames =
                list.stream()
                        .map(item -> item.getAreaName().trim())
                        .distinct()
                        .collect(Collectors.toList());
        int code = 0;
        List<BuildAreaV1> insertAreaList = new ArrayList<>();
        for (String name : areaNames) {
            code++;
            BuildAreaV1 area = new BuildAreaV1();
            area.setParkId(parkId);
            area.setCode(code >= 10 ? "" + code : "0" + code);
            area.setAreaName(name);
            area.setCreateTime(DateUtils.getNowDate());
            area.setCreateBy(SecurityUtils.getUserId());
            insertAreaList.add(area);
        }

        buildAreaService.saveBatch(insertAreaList);
        Map<String, BuildAreaV1> areaMap =
                insertAreaList.stream().collect(Collectors.toMap(BuildAreaV1::getAreaName, o -> o));
        for (DoorImportTemplateDTO dto : list) {
            if (StringUtils.isNotNull(areaMap.get(dto.getAreaName()))) {
                dto.setAreaId(areaMap.get(dto.getAreaName()).getId());
                dto.setAreaCode(areaMap.get(dto.getAreaName()).getCode());
            }
        }
    }

    @Override
    public AjaxResult updateInvitationCode() {

        List<AccessDeviceV1> list =
                accessDeviceService.selectFreeviewDeviceList(new DeviceListSearch());
        List<Long> parkIds =
                list.stream().map(AccessDeviceV1::getParkId).distinct().collect(Collectors.toList());

        UserListSearch search = new UserListSearch();
        search.setParkIds(parkIds);
        List<UserV1> userList = userService.selectUserListV1(search);
        Map<Long, List<UserV1>> userMap =
                userList.stream().collect(Collectors.groupingBy(UserV1::getParkId));

        List<UserV1> updateList = new ArrayList<>(userList.size());
        for (Long parkId : parkIds) {
            List<UserV1> userV1List = userMap.get(parkId);
            if (CollectionUtil.isNotEmpty(userV1List)) {
                List<String> codes = new ArrayList<>(userV1List.size());
                userV1List.forEach(
                        item -> {
                            String code = createInvitationCode(codes);
                            codes.add(code);

                            UserV1 update = new UserV1();
                            update.setId(item.getId());
                            update.setInvitationCode(code);
                            updateList.add(update);
                        });
            }
        }

        boolean isSuccess = userService.updateBatchById(updateList);
        if (!isSuccess) {
            return AjaxResult.error("更新失败");
        }

        return AjaxResult.success("更新成功");
    }

    private String createInvitationCode(List<String> codes) {
        String code = MathUtil.getRandom(6);
        boolean flag = true;
        while (flag) {
            flag = codes.contains(code);
            if (!flag) {
                break;
            }
            code = MathUtil.getRandom(6);
        }
        return code;
    }

    /**
     * ========================================================= openApi
     * =========================================================== *
     */
    @Override
    public AjaxResult getUserList(RemoteUserListRequest request) {

        Map<String, Object> map = new HashMap<>(2);
        map.put("list", new ArrayList<>());
        map.put("total", 0);

        UserListSearch search = OrikaUtil.convert(request, UserListSearch.class);
        search.setParkId(request.getProjectId());
        IPage<UserV1> page = userService.selectUserPageV1(search);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return AjaxResult.success(map);
        }

        List<UserV1> list = page.getRecords();
        List<Long> baseUserIds =
                list.stream().map(UserV1::getBaseUserId).distinct().collect(Collectors.toList());
        List<BaseUserV1> baseUserList = baseUserService.listByIds(baseUserIds);
        Map<Long, BaseUserV1> baseUserMap =
                baseUserList.stream().collect(Collectors.toMap(BaseUserV1::getId, o -> o));

        List<UserListV1VO> vos = OrikaUtil.converts(page.getRecords(), UserListV1VO.class);
        vos.forEach(
                item -> {
                    if (StringUtils.isNotNull(baseUserMap.get(item.getBaseUserId()))) {
                        item.setUserName(baseUserMap.get(item.getBaseUserId()).getUserName());
                        item.setPhone(baseUserMap.get(item.getBaseUserId()).getCellphone());
                    }
                });

        map.put("list", vos);
        map.put("total", page.getTotal());

        return AjaxResult.success(map);
    }

    @Override
    public R<LoginAppUser> getUserInfo(String loginName) {

        List<BaseUserV1> user1 = baseUserService.selectBaseUserV1ByLoginName(loginName);
        if(user1.size()>1){
            log.error("当前房屋下有多个相同用户");
        }
        BaseUserV1 user = user1.get(0);

        if (StringUtils.isNull(user)) {
            return R.fail("用户名或密码错误");
        }

        if (StringUtils.isEmpty(user.getPassword())) {
            user.setPassword(SecurityUtils.encryptPassword("123456"));

            BaseUserV1 update = new BaseUserV1();
            update.setId(user.getId());
            update.setPassword(user.getPassword());

            baseUserService.updateById(update);
        }

        LoginAppUser loginAppUser = new LoginAppUser();
        loginAppUser.setUser(OrikaUtil.convert(user, BaseUserDTO.class));

        return R.ok(loginAppUser);
    }
}
